/*
 * FfmpegMediaReader.h
 *
 *  Created on: 2017年3月3日
 *      Author: chuanjiang.zh
 */

#ifndef FFMPEGMEDIAREADER_H_
#define FFMPEGMEDIAREADER_H_

#include "BasicType.h"
#include "Ffmpeg.h"
#include <string>

extern "C"
{
	#include <libavutil/time.h>
}

class FfmpegMediaReader
{
public:
	FfmpegMediaReader():
		m_width(),
		m_height(),
		m_fps(),
		m_codec(),
		m_channels(),
		m_sampleRate(),
		m_acodec(),
		m_fmtContext()
	{

	}

	virtual ~FfmpegMediaReader()
	{
		close();
	}

	int open(const char* url)
	{
		int rc = avformat_open_input(&m_fmtContext, url, NULL, NULL);
		if (rc != 0)
		{
			return EBADF;
		}

		rc = avformat_find_stream_info(m_fmtContext, NULL);

		int videoIndex = -1;
		AVCodecContext* vContext = 0;
		AVCodec* videoCodec = NULL;
		{
			int idx = av_find_best_stream(m_fmtContext, AVMEDIA_TYPE_VIDEO, -1, -1, &videoCodec, 0);
			if (!videoCodec)
			{
				avformat_close_input(&m_fmtContext);
				return EBADF;
			}

			AVStream* stream = m_fmtContext->streams[idx];
			vContext = stream->codec;

			m_codec = vContext->codec_id;
			m_width = vContext->width;
			m_height = vContext->height;
			if (stream->avg_frame_rate.den > 0)
			{
				m_fps = stream->avg_frame_rate.num / stream->avg_frame_rate.den;
			}
			else if (stream->r_frame_rate.den > 0)
			{
				m_fps = stream->r_frame_rate.num / stream->r_frame_rate.den;
			}
			else
			{
				m_fps = 25;
			}

			if (vContext->extradata_size > 0)
			{
				m_prop.assign((char*)vContext->extradata, vContext->extradata_size);
			}

			videoIndex = idx;
		}

		int audioIndex = -1;
		AVCodecContext* aContext = 0;
		AVCodec* audioCodec = NULL;
		{
			int idx = av_find_best_stream(m_fmtContext, AVMEDIA_TYPE_AUDIO, -1, -1, &audioCodec, 0);
			if (audioCodec)
			{
				AVStream* stream = m_fmtContext->streams[idx];
				aContext = stream->codec;

				m_acodec = aContext->codec_id;
				AVSampleFormat sampleFmt = aContext->sample_fmt;
				m_sampleRate = aContext->sample_rate;
				m_channels = aContext->channels;

				if (aContext->extradata_size > 0)
				{
					m_config.assign((char*)aContext->extradata, aContext->extradata_size);
				}

				audioIndex = idx;
			}
		}

		return 0;
	}

	void close()
	{
		if (m_fmtContext)
		{
			avformat_close_input(&m_fmtContext);
			m_fmtContext = NULL;
		}
	}

	bool isOpen()
	{
		return (m_fmtContext != NULL);
	}

	int read(AVPacket& pkt)
	{
		int rc = av_read_frame(m_fmtContext, &pkt);
		if (rc != 0)
		{
			return rc;
		}

		AVStream* stream = m_fmtContext->streams[pkt.stream_index];

		pkt.pts -= stream->start_time;
		pkt.dts -= stream->start_time;

		/// 转换时间戳到 1/1000000
		AVRational destRate = av_make_q(1, AV_TIME_BASE);
		av_packet_rescale_ts(&pkt, stream->time_base, destRate);

		pkt.stream_index = stream->codec->codec_type;

		return rc;
	}

	static bool isVideo(AVPacket& pkt)
	{
		return (pkt.stream_index == AVMEDIA_TYPE_VIDEO);
	}

	bool isLive()
	{
		return m_fmtContext->duration <= 0;
	}

	int64_t getDuration()
	{
		return m_fmtContext->duration;
	}

public:
	int	m_width;
	int m_height;
	int m_fps;
	AVCodecID	m_codec;
	std::string	m_prop;

	int m_channels;
	int m_sampleRate;
	AVCodecID	m_acodec;
	std::string	m_config;

protected:
	AVFormatContext*	m_fmtContext;


};

#endif /* FFMPEGMEDIAREADER_H_ */
